/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2023 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "adc.h"
#include "spi.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
#include "stdint.h"
#include "stdlib.h"
#include "string.h"
#include "stdbool.h"
#include "hc_sr04.h"
#include "weight.h"
#include "base.h"
//
#include "oled.h"
#include "bmp.h"
//#include "oledfont.h"


/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
extern u8 rx_byte_1;
extern u8 rx_p_1;
extern char rx_data_1[50];
//
extern u8 rx_byte_k210;
extern u8 rx_p_k210;
extern char rx_data_k210[40];

extern u8 rx_byte_mv;
extern u8 rx_p_mv;
extern char rx_data_mv[40];
//
extern u16 tim2_10ms;
extern bool key[2];
extern u8 key_cnt;


/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define ONBEEP HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_RESET);
#define OFFBEEP HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_SET);
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
bool flag_visual = 0;//The acquisition of visual

char rx_message_1[50];
void Rx_pro()
{
	if(rx_p_1)
	{
		if(rx_p_1 == 2)
		{
			if(strcmp(rx_data_1, "ab") == 0)
			{
				sprintf(rx_message_1, "right\n");
				HAL_UART_Transmit(&huart1, (uint8_t *)rx_message_1, strlen(rx_message_1), 50);
			}
		}
		else {
			sprintf(rx_message_1, "error\n");
			HAL_UART_Transmit(&huart1, (uint8_t *)rx_message_1, strlen(rx_message_1), 50);
		}
		memset(rx_data_1,0,50);
		rx_p_1 = 0;
	}
}
/*************************
 * 滤波
 * 参数num:输入一个数组
 * 作用:将数组中重复三个以及以上的数字输出
 * ***********************/
u8 vote(u8 *p)
{
	u8 arr_vote[9] = {0};
	u8 ret = 0;
	for(int8_t i = 0; i <= 5; i++)
	{
		if(i <= 4)
			arr_vote[*(p+i)]++;
		else
		{
			for(int8_t i = 0; i < 9; i++)
				if(arr_vote[i] >= 3)
				{
					ret = i;
					break;
				}
				else
					continue;
		}
	}
	return ret;
}
#if 0
/*************************
 * 多标识滤波
 * 参数f:输入数字的标识
 * 参数n:输入的数字
 * 作用:输出一个含各个标识的数字滤波值的数组,下标为标识,对应下标元素为滤波值
 * 返回值:数组arr[0], 该数组下标为标识,元素为该标识中的滤波值
 * ***********************/
u8* channel_4_filtr(u8 f, u8 n)
{
	static u8 arr[5][5];//1,2,3,4行为标识,元素为同标识的数字
	static u8 i1 = 0, i2 = 0, i3 = 0, i4 = 0;
	switch(f)
	{
	case 1:
		arr[1][i1++] = n;
		if(i1++ >= 5)
		{
			arr[0][1] = vote(arr[1]);
			i1 = 0;
			memset(arr[1], 0, 6);
		}
		break;
	case 2:
		arr[2][i2++] = n;
		if(i2++ >= 5)
		{
			arr[0][2] = vote(arr[2]);
			i2 = 0;
			memset(arr[2], 0, 5);
		}
		break;
	case 3:
		arr[3][i3++] = n;
		if(i3++ >= 5)
		{
			arr[0][3] = vote(arr[3]);
			i3 = 0;
			memset(arr[3], 0, 5);
		}
		break;
	case 4:
		arr[4][i4++] = n;
		if(i4++ >= 5)
		{
			arr[0][4] = vote(arr[4]);
			i4 = 0;
			memset(arr[4], 0, 5);
		}
		break;
	}
	return arr[0];
}
#endif
u8 k210_num[8] = {0};//接受到对应数字的方向//1表示左转,2表示右转,3表示手持且只有一个,4表示路口
u8 des = 0;
void Rx_pro_k210()
{
	char n[1], f[1];
	u8 n_num = 0, f_num = 0;
	static u8 arr[5][5] = {0};//1,2,3,4行为标识,元素为同标识的数字
	static u8 i1 = 0, i2 = 0, i3 = 0, i4 = 0;
	u8 *p;
	if(rx_p_k210)
	{
		sprintf(rx_message_1, "%s\n",rx_data_k210);
		HAL_UART_Transmit(&huart1, (uint8_t *)rx_message_1, strlen(rx_message_1), 50);
		if(rx_p_k210 == 3)
		{
//			flag_visual = 1;
			sprintf(rx_message_1, "rx right\n");
			HAL_UART_Transmit(&huart1, (uint8_t *)rx_message_1, strlen(rx_message_1), 50);
			sscanf(rx_data_k210, "%c:%c", f, n);
			f_num = atoi(f);
			n_num = atoi(n);
#if 1
/*********************滤波***********************/
			switch(f_num)
			{
			case 1:
				if(i1++ == 5)
				{
					arr[0][1] = vote(arr[1]);
					i1 = 0;
				}
				else
					arr[1][i1] = n_num;

				break;
			case 2:
				if(i2++ == 5)
				{
					arr[0][2] = vote(arr[2]);
					i2 = 0;
				}
				else
					arr[2][i2] = n_num;

				break;
			case 3:
				if(i3++ == 5)
				{
					arr[0][3] = vote(arr[3]);
					i3 = 0;
				}
				else
					arr[3][i3] = n_num;

				break;
			case 4:
				if(i4++ == 5)
				{
					arr[0][4] = vote(arr[4]);
					i4 = 0;
				}
				else
					arr[4][i4] = n_num;
				break;
			default:break;
			}
#endif
/*********************存储***********************/
#if 1
			if(des == 0)
			{
				k210_num[ arr[0][3]-1 ] = 3;
				des = arr[0][3];
			}
			else {
				k210_num[ arr[0][1]-1 ] = 1;
				k210_num[ arr[0][2]-1 ] = 2;
				k210_num[ arr[0][4]-1 ] = 4;
				for(u8 i = 0; i <= 8; i++)
				{
					sprintf(rx_message_1, "%d",k210_num[i]);
					HAL_UART_Transmit(&huart1, (uint8_t *)rx_message_1, strlen(rx_message_1), 50);
				}
				sprintf(rx_message_1, " des=%d\n", des);
				HAL_UART_Transmit(&huart1, (uint8_t *)rx_message_1, strlen(rx_message_1), 50);
			}
#endif
		}
		else
		{
			sprintf(rx_message_1, "k210 error\n");
			HAL_UART_Transmit(&huart1, (uint8_t *)rx_message_1, strlen(rx_message_1), 50);
		}
		memset(rx_data_k210,0,50);
		rx_p_k210 = 0;
	}
}

void Rx_pro_mv()
{
	if(rx_p_mv)
	{
		sprintf(rx_message_1, "%s\n",rx_data_mv);
		HAL_UART_Transmit(&huart1, (uint8_t *)rx_message_1, strlen(rx_message_1), 50);
		if(rx_p_mv == 2)
		{
			//flag_visual = 1;
			sprintf(rx_message_1, "\n");
			HAL_UART_Transmit(&huart1, (uint8_t *)rx_message_1, strlen(rx_message_1), 50);
//			sscanf(rx_data_k210);
		}
		else
		{
			sprintf(rx_message_1, "usart mv error\n");
			HAL_UART_Transmit(&huart1, (uint8_t *)rx_message_1, strlen(rx_message_1), 50);
		}
		memset(rx_data_mv,0,50);
		rx_p_mv = 0;
	}
}
/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */
	u16 Weight_Shiwu;
	u8 distance;//超声波距�?
	u8 junction = 0;//十字路口
	//mode : 表示des是�?�过哪些方法获得�?,2表示通过按键 1表示先称重后识别 0表示先识别后称重
	u8 mode = 0;
	u8 trail[8] = {0};
	bool flag_des = 0;//flag_des: 0表示未获得目的地, 1表示获得目的�?
	bool flag_wei = 0;//flag_wei: 0表示未称�?, 1表示已称�?
	bool flag_20cm = 0;//flag_20cm: 0表示未碰�? 1表示已碰�?
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_TIM3_Init();
  MX_USART1_UART_Init();
  MX_TIM2_Init();
  MX_ADC3_Init();
  MX_USART2_UART_Init();
  MX_USART3_UART_Init();
  MX_SPI1_Init();
  /* USER CODE BEGIN 2 */

	HAL_UART_Receive_IT(&huart1, &rx_byte_1, 1);
	HAL_UART_Receive_IT(&huart2, &rx_byte_k210, 1);
	HAL_UART_Receive_IT(&huart3, &rx_byte_mv, 1);
	HAL_TIM_Base_Start_IT(&htim2);
	HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_1);
	//
	OLED_Init();
	OLED_ColorTurn(0);//0正常显示 1 反色显示
	OLED_DisplayTurn(0);//0正常显示 1 屏幕翻转显示
	OLED_Refresh(); //每次更改后，�?????要刷�?????

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
	OFFBEEP;
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		if(tim2_10ms >= 10)
		{
			tim2_10ms = 0;
			//in
#if 0
			Key();
			Weight_Shiwu = Get_Weight();
			trail[0] = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_7);
			trail[1] = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0);
			trail[2] = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1);
			trail[3] = HAL_GPIO_ReadPin(GPIOF, GPIO_PIN_11);
			trail[4] = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_10);

			trail[5] = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_11);
			trail[6] = HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_4);
			trail[7] = HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_5);
			distance = Get_distance();
#endif
			
			if(rx_p_1)
			{
				int index = rx_p_1;
				HAL_Delay(1);
				if(index == rx_p_1)
					Rx_pro();
			}
			if(rx_p_k210)
			{
				int index = rx_p_k210;
				HAL_Delay(1);
				if(index == rx_p_k210)
					Rx_pro_k210();
			}
			
//			if(rx_p_mv)
//			{
//				int index = rx_p_mv;
//				HAL_Delay(1);
//				if(index == rx_p_mv)
//					Rx_pro_mv();
//			}

			//pro
			
#if 0
			if(Weight_Shiwu >= 200)//acquisition of weight
			{
				flag_wei = 1;
				sprintf(rx_message_1, "%d\n",Weight_Shiwu );
				HAL_UART_Transmit(&huart1, (uint8_t *)rx_message_1,strlen(rx_message_1),50);//发�?�到串口
			}
			else {
				flag_wei = 0;
			}
#endif

#if 0
			if(distance <= 20)//碰壁�?
			{
				flag_20cm = 1;
				//-------motor control begin//转向后直�?

				//-------control end
			}
			if(!flag_20cm)
			{

			}
#endif

#if 0
			if(!flag_des)//如果没有获得目的�?
			{
				if(!key[0] && key_cnt == 2)//如果按键1按下
				{
					des = 1;
					flag_des = 1;
					mode = 2;
				}
				else if(!key[1] && key_cnt == 2){//或�?�按�?2按下
					des = 2;
					flag_des = 1;
					mode = 2;
				}
				else if(flag_visual){//或�?�没有按键按下且识别到了卡片数字
					des = k210_num[0];
					if(flag_wei)//如果这时候已经有200g
						mode = 1;
					else //否则
						mode = 0;
					flag_des = 1;
				}
			}
			if(mode == 0 && flag_wei && !flag_20cm)//如果计划0且载重完成且未碰�?
			{
				if(des <=4)
				{
					//-------motor control begin//直走到第�?个十字路�?

					//-------control end
					if(des == 1)
					{
						//-------motor control begin//左转

						//-------control end
					}
					else if(des == 2)
					{
						//-------motor control begin//右转

						//-------control end
					}
					else
					{
						//-------motor control begin//直走到第二个十字路口

						//-------control end
						if(des == 3)
						{
							if(k210_num[2] == 0)
							{
								//-------motor control begin//左转且前�?

								//-------control end
							}
							else
							{
								//-------motor control begin//右转且前�?

								//-------control end
							}
						}
						else if(des == 4)
						{
							if(k210_num[4] == 0)
							{
								//-------motor control begin//左转且前�?

								//-------control end
							}
							else
							{
								//-------motor control begin//右转且前�?

								//-------control end
							}
						}
					}
				}
				else if(des >= 5)
				{
					//-------motor control begin//直走到第三个十字路口

					//-------control end
					if()
				}
			}
			else if (mode == 1) {//plan 2

			}
			else if (mode == 2) {//plan 1
				if(des == 1)
				{
					//-------motor control begin//直走到第�?个十字路�?

					//-------control end
					//-------motor control begin//左转

					//-------control end
				}
				else if(des == 2)
				{
					//-------motor control begin//直走到第�?个十字路�?

					//-------control end
					//-------motor control begin//右转

					//-------control end
				}
			}
#endif

			//out
			
#if 0//gray
			for(int i = 0; i < 8; i++)
			{
				OLED_ShowNum(1+16*i ,20 ,trail[i] ,1 ,16);
				OLED_Refresh();
			}
#endif
		}
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC;
  PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
